/*
 * Copyright (c) 2012, Marcin Czekaj
 * All rights reserved.
 *
 * This software is open-source under the BSD license; see LICENSE.TXT for a description.
 */
package pl.edu.uj.fais.controller;

import java.util.HashSet;
import java.util.Set;

import pl.edu.uj.fais.graph.elements.Link;
import pl.edu.uj.fais.graph.elements.Node;
import pl.edu.uj.fais.graph.elements.ProxyNode;
import pl.edu.uj.fais.gui.GraphCanvas;
import pl.edu.uj.fais.mode.GraphMode;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.picking.PickedState;

public class SelectionController {
    
    private static Controller controller = Controller.getInstance();
    
    public static boolean isSingleNodeSelected() {
        
        GraphCanvas canvas = controller.getGraphCanvas();
        GraphMode mode = controller.getGraphMode();
        
        if (canvas != null) {
            
            PickedState<Node> selectedNodes = canvas.getPickedVertexState();
            PickedState<Link> selectedLinks = canvas.getPickedEdgeState();
            
            if (selectedLinks.getPicked().size() > 0) {
                return false;
            }
            
            if (selectedNodes.getPicked().size() == 1) {
                if (mode == GraphMode.HYPERGRAPH) {
                    Node node = (Node) selectedNodes.getSelectedObjects()[0];
                    return !node.isProxyNode();
                } else {
                    return true;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    
    public static void deleteSelected() {
        
        GraphCanvas canvas = controller.getGraphCanvas();
        Graph<Node, Link> graph = controller.getGraph();
        
        PickedState<Node> nodes = canvas.getPickedVertexState();
        PickedState<Link> links = canvas.getPickedEdgeState();
        
        // copy selected vertices before unselecting
        Set<Node> selectedNodes = new HashSet<>(nodes.getPicked());
        Set<Link> selectedLinks = new HashSet<>(links.getPicked());
        
        unselectAll();
        
        Set<Node> nodesToDelete = new HashSet<>();
        Set<Link> linksToDelete = new HashSet<>();
        
        for (Link link : selectedLinks) {
            checkProxyToDelete(link, nodesToDelete);
            linksToDelete.add(link);
        }
        
        for (Node node : selectedNodes) {
            
            for (Link link : graph.getIncidentEdges(node)) {
                checkProxyToDelete(link, nodesToDelete);
                linksToDelete.add(link);
            }
            
            nodesToDelete.add(node);
        }
        
        for (Link link : linksToDelete) {
            graph.removeEdge(link);
        }
        
        for (Node node : nodesToDelete) {
            graph.removeVertex(node);
        }
        
        canvas.repaint();
        
        controller.setChanged();
    }
    
    public static void selectAll() {
        
        GraphCanvas canvas = controller.getGraphCanvas();
        Graph<Node, Link> graph = controller.getGraph();
        
        PickedState<Node> nodes = canvas.getPickedVertexState();
        PickedState<Link> links = canvas.getPickedEdgeState();
        
        for (Link link : graph.getEdges()) {
            links.pick(link, true);
        }
        
        for (Node node : graph.getVertices()) {
            nodes.pick(node, true);
        }
    }
    
    public static void unselectAll() {
        
        GraphCanvas canvas = controller.getGraphCanvas();
        
        PickedState<Node> nodes = canvas.getPickedVertexState();
        PickedState<Link> links = canvas.getPickedEdgeState();
        
        nodes.clear();
        links.clear();
    }
    
    public static void selectHyperEdge(Node node) {
        setHyperEdgeSelected(node, true);
    }
    
    public static void unselectHyperEdge(Node node) {
        setHyperEdgeSelected(node, false);
    }
    
    private static void checkProxyToDelete(Link link, Set<Node> nodesToDelete) {
        
        GraphMode mode = controller.getGraphMode();
        Graph<Node, Link> graph = controller.getGraph();
        
        if (mode == GraphMode.HYPERGRAPH) {
            ProxyNode proxy = link.getProxyNode();
            if (graph.getIncidentEdges(proxy).size() <= 2) {
                nodesToDelete.add(proxy);
            }
        }
    }
    
    private static void setHyperEdgeSelected(Node node, boolean selected) {
        
        GraphCanvas canvas = controller.getGraphCanvas();
        Graph<Node, Link> graph = controller.getGraph();
        
        PickedState<Node> nodes = canvas.getPickedVertexState();
        PickedState<Link> links = canvas.getPickedEdgeState();
        
        nodes.pick(node, selected);
        
        for (Link adjacentLink : graph.getIncidentEdges(node)) {
            links.pick(adjacentLink, selected);
        }
    }
}
